/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import { Heap } from '../../../../src/common/util/heap';

enum Prio {
  FIRST = 0,
  HEAVY = 1,
  MEDIUM = 2,
  LIGHT = 3,
  LAST = 4
}

class Q {
  prio: Prio;
  id: number;

  constructor(p: Prio, i: number) {
    this.id = i;
    this.prio = p;
  }
}

const QComparator = (a: Q, b: Q) => {
  return a.prio - b.prio;
};

describe('test heap', () => {
  test('test queue push&pop', () => {
    const heap = new Heap<Q>(QComparator);
    let q1 = new Q(Prio.FIRST, 1);
    let q2 = new Q(Prio.HEAVY, 2);
    let q3 = new Q(Prio.MEDIUM, 3);
    let q4 = new Q(Prio.LIGHT, 4);
    let q5 = new Q(Prio.LAST, 5);
    heap.push(q1);
    heap.push(q2);
    heap.push(q3);
    heap.push(q4);
    heap.push(q5);
    expect(heap.pop()!.id).toBe(1);
    expect(heap.pop()!.id).toBe(2);
    expect(heap.pop()!.id).toBe(3);
    expect(heap.pop()!.id).toBe(4);
    expect(heap.pop()!.id).toBe(5);
    q1 = new Q(Prio.LAST, 1);
    q2 = new Q(Prio.LIGHT, 2);
    q3 = new Q(Prio.MEDIUM, 3);
    q4 = new Q(Prio.HEAVY, 4);
    q5 = new Q(Prio.FIRST, 5);
    heap.push(q1);
    heap.push(q2);
    heap.push(q3);
    heap.push(q4);
    heap.push(q5);
    expect(heap.pop()!.id).toBe(5);
    expect(heap.pop()!.id).toBe(4);
    expect(heap.pop()!.id).toBe(3);
    expect(heap.pop()!.id).toBe(2);
    expect(heap.pop()!.id).toBe(1);
    heap.push(new Q(Prio.HEAVY, 1));
    heap.push(new Q(Prio.FIRST, 2));
    const x: Q = heap.pop()!;
    heap.push(new Q(Prio.FIRST, 3));
    heap.push(x);
    heap.push(new Q(Prio.LAST, 4));
    heap.push(new Q(Prio.LAST, 5));
    expect(heap.pop()!.id).toBe(3);
    expect(heap.pop()!.id).toBe(2);
    expect(heap.pop()!.id).toBe(1);
    expect(heap.pop()!.id).toBe(4);
    expect(heap.pop()!.id).toBe(5);
  });

  test('test queue clear', () => {
    const heap = new Heap<Q>(QComparator);
    heap.push(new Q(Prio.HEAVY, 1));
    heap.push(new Q(Prio.FIRST, 2));
    heap.clear();
    expect(heap.empty()).toBe(true);
  });

  test('test queue peek', () => {
    const heap = new Heap<Q>(QComparator);
    heap.push(new Q(Prio.FIRST, 1));
    heap.push(new Q(Prio.FIRST, 2));
    expect(heap.peek()!.id).toBe(1);
    heap.pop();
    heap.pop();
    heap.push(new Q(Prio.LAST, 1));
    heap.push(new Q(Prio.LAST, 2));
    expect(heap.peek()!.id).toBe(1);
  });

  test('test queue update', () => {
    const heap = new Heap<Q>(QComparator);
    const q1 = new Q(Prio.FIRST, 1);
    const q2 = new Q(Prio.HEAVY, 2);
    const q3 = new Q(Prio.MEDIUM, 3);
    const q4 = new Q(Prio.LIGHT, 4);
    const q5 = new Q(Prio.LAST, 5);
    heap.push(q1);
    heap.push(q2);
    heap.push(q3);
    heap.push(q4);
    heap.push(q5);
    q1.prio = Prio.LAST;
    q2.prio = Prio.LIGHT;
    q3.prio = Prio.MEDIUM;
    q4.prio = Prio.HEAVY;
    q5.prio = Prio.FIRST;
    heap.update(q1);
    heap.update(q2);
    heap.update(q3);
    heap.update(q4);
    heap.update(q5);
    expect(heap.pop()!.id).toBe(5);
    expect(heap.pop()!.id).toBe(4);
    expect(heap.pop()!.id).toBe(3);
    expect(heap.pop()!.id).toBe(2);
    expect(heap.pop()!.id).toBe(1);
  });
});
